package com.jzoom.zoom.web;

import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jzoom.zoom.ioc.impl.ZoomIoc;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.jzoom.zoom.common.ConfigurationConstants;
import com.jzoom.zoom.common.config.ConfigReader;
import com.jzoom.zoom.common.filter.Filter;
import com.jzoom.zoom.common.filter.OrFilter;
import com.jzoom.zoom.common.filter.pattern.PatternFilterFactory;
import com.jzoom.zoom.common.res.ClassResolvers;
import com.jzoom.zoom.common.res.ResLoader;
import com.jzoom.zoom.common.res.ResScanner;
import com.jzoom.zoom.common.utils.CachedClasses;
import com.jzoom.zoom.ioc.IocContainer;
import com.jzoom.zoom.web.action.ActionHandler;
import com.jzoom.zoom.web.action.impl.SimpleActionBuilder;
import com.jzoom.zoom.web.configuration.SimpleConfigBuilder;
import com.jzoom.zoom.web.router.Router;
import com.jzoom.zoom.web.router.impl.BracesRouterParamRule;
import com.jzoom.zoom.web.router.impl.SimpleRouter;
import com.jzoom.zoom.web.utils.WebUtils;

public class ZoomWeb {
	private Router router;

	private IocContainer ioc;


	private static Log log = LogFactory.getLog(ZoomWeb.class);
	long first = System.currentTimeMillis();
	
	public void init() {
		
		printLogo();
        // 初始化ioc容器
        ioc = new ZoomIoc();
        ioc.getIocClassLoader().append(IocContainer.class,ioc,true);
        WebUtils.setIoc(ioc);

		/// 加载整个项目的主配置
		loadApplicationConfig();
		// 扫描整个资源, .class .jar 其他配置文件等
		scanResources();
		// 初始化router
		createRouter();

		resolveClasses();

		printTime();


		WebUtils.setStartupSuccess();

	}
    private void resolveClasses() {
        // 初始化classInfo
        ClassResolvers classResolvers = new ClassResolvers(new SimpleConfigBuilder(ioc),new SimpleActionBuilder(ioc,router));

        ioc.getIocClassLoader().append(ClassResolvers.class,classResolvers,true);

        classResolvers.visit(ResScanner.me());
    }

    private void createRouter() {
	    ioc.getIocClassLoader().append(Router.class, new SimpleRouter(new BracesRouterParamRule()),true);
        router = ioc.get(Router.class);
    }



    private void printLogo() {
		log.info("==============================Startup Zoom==============================");

		System.out.println("____  ___    ___\n" + "  /  / _ \\  / _ \\ |\\    /|\n"
				+ " /  | (_) || (_) || \\  / |    \n" + "/___ \\___/  \\___/ |  \\/  |\n");
	}

	private void printTime() {
		RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
		long startTime = bean.getStartTime();
		long now = System.currentTimeMillis();
		log.info(String.format(
				"==============================Startup Zoom  in [%d] ms , JVM runing time [%d] ms==============================",
				now - first, now - startTime));
	}




	class JarFilter implements Filter<File> {

		private Filter<String> filter;

		public JarFilter(Filter<String> filter) {
			this.filter = filter;
		}

		@Override
		public boolean accept(File value) {
			return filter.accept(value.getName());
		}

	}

	@SuppressWarnings("unchecked")
	private void scanResources() {
		Filter<File> jarFilter = null;
		String jar = ConfigReader.getDefault().getString(ConfigurationConstants.SCAN_JAR);
		if (!StringUtils.isEmpty(jar)) {
			jarFilter = new OrFilter<File>(ResScanner.fastFilter,
					new JarFilter(PatternFilterFactory.createFilter(jar)));
		} else {
			// 不扫描jar
			jarFilter = ResScanner.fastFilter;
		}

		try {
			ResScanner.me().scan(ZoomWeb.class.getClassLoader(), jarFilter);
		} catch (IOException e) {
			throw new RuntimeException("扫描解析文件出错，请确认权限是否满足要求");
		}

	}

	/**
	 * 获取应用程序全局配置
	 * 
	 * @return
	 */
	private void loadApplicationConfig() {
		// 加载全局配置

		File file = ResLoader.getResourceAsFile("application.properties");
		if (file == null) {
			file = ResLoader.getResourceAsFile("application.json");
		}

		if (file == null) {
			// 目前这个版本支持两种主配置，properties/yml
			//throw new RuntimeException("启动失败，请确认application.properties或application.json存在");
			return;
		}
		ConfigReader.getDefault().load(file);

	}

	public void destroy() {

		if (ioc != null) {
			ioc.destroy();
			ioc = null;
		}

		router = null;

		WebUtils.setIoc(null);

		CachedClasses.clear();
		PatternFilterFactory.clear();
		ResScanner.me().destroy();
	}

	public boolean handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		// 路由
		
		ActionHandler action = router.match(request);
		if (action == null) {
			return false;
		}

		action.handle(request, response);
		//throw new StatusException.NotAllowedHttpMethodException(request.getMethod());
		
		return true;
	}

	public IocContainer getIoc() {
		return ioc;
	}

}
